package com.mspbots.core.wise.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.mspbots.core.AbstractBaseServiceImpl;
import com.mspbots.core.wise.controller.params.TenantUserParams;
import com.mspbots.core.wise.controller.params.UserMappingParams;
import com.mspbots.core.wise.mapper.TenantUserMapper;
import com.mspbots.core.wise.model.TenantUser;
import com.mspbots.core.wise.model.dto.UserMappingResponse;
import com.mspbots.core.wise.model.dto.UserResponse;
import com.mspbots.core.wise.service.TenantUserMappingService;
import com.mspbots.core.wise.service.TenantUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author billb
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TenantUserServiceImpl extends AbstractBaseServiceImpl<TenantUserMapper, TenantUser> implements TenantUserService {

    private final TenantUserMappingService usersMappingService;

    @Override
    public TenantUser lastOne(Long tenant) {
        return this.baseMapper.selectLastOne(tenant);
    }

    @Override
    public List<TenantUser> getTenantUsers(Long tenantId, String email, String originalMail) {
        if (StringUtils.isEmpty(email)) {
            return null;
        }
        QueryWrapper<TenantUser> tenantUserQueryWrapper = new QueryWrapper<>();
        tenantUserQueryWrapper.eq("lower(email)", email.toLowerCase())
                .or().eq("lower(email)", StringUtils.isEmpty(originalMail) ? "" : originalMail.toLowerCase())
                .eq("tenant_id", tenantId);
        return this.baseMapper.selectList(tenantUserQueryWrapper);
    }

    @Override
    public IPage<UserResponse> getPage(IPage<TenantUser> page, TenantUserParams userParams) {
        QueryWrapper<TenantUser> wrapper = Wrappers.query();
        wrapper.eq(userParams.getTenantId() != null, "tenant_id", userParams.getTenantId())
                .eq(userParams.getDepartmentId() != null, "department_id", userParams.getDepartmentId())
                .eq("enable", true)
                .ne(!StringUtils.isEmpty(userParams.getLicenseClassNot()), "license_class", userParams.getLicenseClassNot())
                .like(!StringUtils.isEmpty(userParams.getUsername()), "upper(CONCAT(firstname,' ',lastname))", StringUtils.isEmpty(userParams.getUsername()) ? "" : userParams.getUsername().toUpperCase());

        IPage<TenantUser> tenantUserPage = super.page(page, wrapper);

        IPage<UserResponse> userResponsePage = new Page<>();
        BeanUtils.copyProperties(tenantUserPage, userResponsePage);
        userResponsePage.setRecords(tenantUserPage.getRecords().parallelStream().map(user -> {
            UserResponse response = UserResponse.builder().id(user.getId()).build();
            BeanUtils.copyProperties(user, response);
            UserMappingResponse userMapping = this.usersMappingService
                    .findByOne(UserMappingParams.builder().tenantId(user.getTenantId())
                            .tenantUserId(user.getId())
                            .build());

            if (!ObjectUtils.isEmpty(userMapping) && (user.getEmail() != null && !user.getEmail().contains("#EXT#"))) {
                response.setTeamsUserName(userMapping.getTeamsUserName());
                response.setTeamsUserId(userMapping.getTeamsUserId());
                response.setTsheetUserId(userMapping.getSheetUserId());
                response.setTsheetUserName(userMapping.getTsheetUserName());
            }

            TenantUser manager = this.getById(user.getManager());
            if (!ObjectUtils.isEmpty(manager)) {
                response.setManagerUserName(manager.getFirstname() + " " + manager.getLastname());
            }
            return response;
        }).collect(Collectors.toList()));
        return userResponsePage;
    }

    @Override
    public List<TenantUser> selectByManagerId(Long manager) {
        QueryWrapper<TenantUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("manager", manager);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<TenantUser> getMessageSwitch(List<Long> userList) {
        return this.baseMapper.getMessageSwitch(userList);
    }

    @Override
    public int updateAll(Long id, TenantUser tenantUser) {
        tenantUser.setId(id);
        return this.baseMapper.updateAllColumnById(tenantUser);
    }

    @Override
    public TenantUser selectOneByIdentifier(TenantUser t) {
        TenantUser user = super.getOne(new QueryWrapper<>(t).last("LIMIT 1"));
        Optional.ofNullable(user).ifPresent(u -> {
            if (null != user.getSkills()) {
                Iterator<JsonNode> nodeJson = user.getSkills().elements();
                List<String> list = new ArrayList<>();
                while (nodeJson.hasNext()) {
                    JsonNode node = nodeJson.next();
                    if (null != node.findValue("skill")) {
                        list.add(node.findValue("skill").get("name").asText());
                    }
                }
                user.setSkillNames(list);
            }
            if (null != user.getTeamNames()) {
                Iterator<JsonNode> nodeJson = user.getTeamNames().elements();
                List<String> list = new ArrayList<>();
                while (nodeJson.hasNext()) {
                    JsonNode node = nodeJson.next();
                    list.add(node.get("name").asText());
                }
                user.setTeamNameList(list);
            }
        });
        return user;
    }


}
